package com.wmzdq.config;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Source;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.CharSet;
import org.aspectj.lang.annotation.Aspect;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.wmzdq.common.IMenuService;
import com.wmzdq.security.SecurityMetadataSource;
//@enableWebMvc 千万不能加，加了会出问题
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
@ComponentScan(basePackages={"com.wmzdq.controller","com.wmzdq.framework.controller","com.wmzdq.test.controller"},useDefaultFilters=false,includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value=Controller.class)})
@ComponentScan(basePackages={"com.wmzdq.config",},useDefaultFilters=false,includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value=Aspect.class)})
public class WebMvcConfiguaration extends DelegatingWebMvcConfiguration  {

    
    //添加 HandlerMethodArgumentResolver 接口，见有道云笔记
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers){
        //支持获取@AuthenticationPrincipal
        argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
    }
    
    //springmvc的国际化，可以不用，默认就是 AcceptHeaderLocaleResolver,具体看有道云笔记
    @Bean(name="localeResolver")
    public AcceptHeaderLocaleResolver localeResolver(){
        return new AcceptHeaderLocaleResolver();
    }
    
    //一定要加！！不然自定义拦截器 无法生效
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        
        return super.requestMappingHandlerMapping();
    }
    
    //定义拦截器
    @Bean
    public LogInterceptor logInterceptor(){
        LogInterceptor log=new LogInterceptor();
        return log;
    }
    
    //添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(logInterceptor()).
      //添加拦截器的作用地址
                  addPathPatterns("/**").
                  excludePathPatterns("/images/**")
              .excludePathPatterns("/js/**")
              .excludePathPatterns("/css/**");
      
    }
    
    @Bean(name="multipartResolver")  
    public CommonsMultipartResolver commonsMultipartResolver(){
        CommonsMultipartResolver upload=new CommonsMultipartResolver();
        upload.setDefaultEncoding("UTF-8");
        return upload;
        
    }
    
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/jsp/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setOrder(0);
        return viewResolver;
    }
    
    //把viewResolver添加到容器中
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(viewResolver());
        
    }
    
    @Bean(name="validatorMessageSource")
    public ReloadableResourceBundleMessageSource validMessageSource(){
        ReloadableResourceBundleMessageSource valid=new ReloadableResourceBundleMessageSource();
        valid.setBasename("classpath:validator_messages");
        valid.setDefaultEncoding("UTF-8");
        return valid;
    }
    
    //hibernate使用的错误提示
    @Override  
    public Validator getValidator() {  
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();  
        validator.setValidationMessageSource(validMessageSource());
        validator.setProviderClass(HibernateValidator.class);
        return validator;  
    }  
    
    @Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter(){
        FastJsonHttpMessageConverter converter=new FastJsonHttpMessageConverter();
        List<MediaType> list=new ArrayList<MediaType>();
        list.add(MediaType.TEXT_HTML);
        list.add(MediaType.APPLICATION_JSON);
        
        converter.setSupportedMediaTypes(list);
        converter.setFeatures(SerializerFeature.QuoteFieldNames,SerializerFeature.WriteDateUseDateFormat);
        return converter;

    }

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        
        Charset charset=Charset.forName("UTF-8");
        StringHttpMessageConverter converter=new StringHttpMessageConverter(charset);
        
        converters.add(fastJsonHttpMessageConverter());
        converters.add(converter);
        converters.add(new ResourceHttpMessageConverter());
        converters.add(new SourceHttpMessageConverter<Source>());
        converters.add(new AllEncompassingFormHttpMessageConverter());
        
    }
    
    @Bean(name="restTemplate")
    public RestTemplate restTemplate(){
        RestTemplate template=new RestTemplate();
        List<HttpMessageConverter<?>> messageConverters=new ArrayList<HttpMessageConverter<?>>();
        messageConverters.add(fastJsonHttpMessageConverter());
        template.setMessageConverters(messageConverters);
        return template;
    }
    
}
